package cn.com.callback

import cn.com.kh.KHFileUtil;
import cn.com.kh.KHUtil;
import net.sf.json.JSONArray;
import cn.com.elite.EliteBean;
import net.sf.json.JSONObject
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import cn.com.elite.Util;
import cn.com.elite.PropertiesUtil;
import cn.com.elite.SendBatchMail;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class EmailSendTask implements CallBackInvoke {
    private static final Log log = LogFactory.getLog(EmailSendTask.class);

    public void doCallBack(EliteBean eliteBean, String callBack, Map map, String body) {

        log.debug("批量发送邮件任务执行开始...");

        // 定义发送批量邮件参数--EX
        List<Map<String, Object>> exsendList = new ArrayList<Map<String, Object>>();

        // 定义发送批量邮件参数--UM
        List<Map<String, Object>> umsendList = new ArrayList<Map<String, Object>>();

        //获取配置文件信息
        PropertiesUtil properties = new PropertiesUtil();
        def emaildir = properties.readValue("emaildir");
        def fileStore = properties.readValue("fileStore");
        def pdfChangeUrl = properties.readValue("crmip");

        // Exchange账号配置
        def exhost = properties.readValue("ex_host");
        def exsendAdderss = properties.readValue("ex_username");
        def exusername = properties.readValue("ex_username");
        def expassword = properties.readValue("ex_password");

        // Umail账号配置
        def umhost = properties.readValue("um_host");
        def umsendAdderss = properties.readValue("um_username");
        def umusername = properties.readValue("um_username");
        def umpassword = properties.readValue("um_password");
        def port = 25;
        JSONArray array = new JSONArray();

        log.debug("获取配置文件信息完成,Exchange:" + exsendAdderss + " UMail:" + umsendAdderss);

        //查询待发送任务
        String selectSQL =
                '''SELECT
                        tk.rec_guid REC_GUID,
                        tk.batch_id BATCH_ID,
                        tk.email EMAIL,
                        tk.content CONTENT,
                        nvl ( tk.contenttype, 'txt' ) CONTENT_TYPE,
                        tk.pipe PIPE,
                        tk.SUBJECT SUBJECT,
                        tk.trialcount TRIAL_COUNT,
                        tk.trialcountlimit TRIAL_COUNT_LIMIT,
                        tk.template_id TEMPLATE_ID,
                        nvl ( dt.uploadflag, 0 ) UPLOAD_FLAG
                   FROM
                        email_send_task tk
                        LEFT JOIN email_send_batch eb ON tk.batch_id = eb.batch_id
                        LEFT JOIN doctemplate dt ON tk.template_id = dt.doctemplate_id 
                   WHERE
                        eb.batchstate = 0 
                        AND eb.checkstate IN ( 0, 2 ) 
                        AND tk.expectedstartdate < sysdate 
                        AND tk.state = 0 
                        AND tk.trialcount < tk.trialcountlimit 
                        AND rownum <= 300 
                   ORDER BY
                        tk.trialcount,
                        tk.priority     
                ''';

        def resultList = eliteBean.chaxun_sql(selectSQL, "dataSource");
        if (resultList.size() > 0) {
            array = JSONArray.fromObject(resultList);
        }

        log.debug("邮件批量发送抽取数据SQL:" + selectSQL + " -查询结果数量:" + resultList.size());

        //邮件正文写到本地的临时目录
        String mail_HtmlPath = properties.readValue("mail_HtmlPath");

        //邮件正文html文件所在服务器访问URL
        String mail_htmlFileURL = properties.readValue("mail_htmlFileURL");

        //邮件地址正则校验
        String mail_AddressCheckReg = properties.readValue("mail_AddressCheckReg");

        String mailPath = properties.readValue("MAILPath");

        //循环处理待发送任务 生成pdf文件，后续统一执行发送
        String pdfTempPath = "";


        JSONObject json = new JSONObject();
        List attachDeleteList = new ArrayList();
        for (int i = 0; i < array.size(); i++) {
            try {
                json = array.get(i);
                Map<String, Object> receviceMap = new HashMap<String, Object>();
                List attachmentList = new ArrayList();

                String batchId = json.getString("BATCH_ID"); //批次号
                String templateId = json.getString("TEMPLATE_ID"); //模板ID

                int uploadFlag = json.getInt("UPLOAD_FLAG"); //模板附件数量
                def pipe = json.get("PIPE"); //发送通道

                String recGuid = json.getString("REC_GUID"); //Guid
                String receviceAddress = json.getString("EMAIL"); ////获取接收邮箱
                String subject = json.getString("SUBJECT"); //邮件主题
                def docGroupSql = "select t.docGroup_id  from doctemplate t where doctemplate_id = '" + templateId + "'";
                List docGroupList = eliteBean.chaxun_sql(docGroupSql, "dataSource");
                def contents = "";
                def docGroupId = "";
                def content = json.getString("CONTENT");//邮件内容
                def contentType = json.getString("CONTENT_TYPE"); //获取邮件正文类型
                def trialCount = json.getString("TRIAL_COUNT"); //尝试次数
                def trialCountLimit = json.getString("TRIAL_COUNT_LIMIT"); //最大尝试次数
                docGroupId = docGroupList[0].getAt("docGroup_id");//获取模板父级id
                // 将邮件发送的邮件内容临时文件路径处理
                def emailpath = emaildir + Util.getNowString("yyyy-MM-dd") + "/" + recGuid + ".eml";
                def relativepath = "/email/" + Util.getNowString("yyyy-MM-dd") + "/" + recGuid + ".eml";
                if (docGroupId == "C6ZR0C") { //当模板父级为对账单模块时，邮件正文添加提示话术，添加pdf文件附件
                    def messageSql = "select t.message  from preferences t where doctemplate_id = '" + templateId + "'";
                    List messageList = eliteBean.chaxun_sql(messageSql, "dataSource");
                    contents = messageList[0].getAt("message");//获取模板父级id;//改为上次数据库中存的话术，或者在doctemplate中添加message字段把给说有父级为C6ZR0C的数据赋值
                    // 将小印章图片换打印章图片（在outlook会直接显示为实际大小）
                    String contentTemp = StringUtils.replace(content, "http://www.msjyfund.com.cn/data/kefu/seal_small.png", "http://www.msjyfund.com.cn/data/kefu/seal.png");
                    // 将邮件正文内容中的外网URL换成本地(服务器无法访问外网)
                    contentTemp = StringUtils.replace(content, "http://www.msjyfund.com.cn/data/kefu/", "http://127.0.0.1:8010/ngs/fs/get?file=sms/images/");

                    String line = null;
                    StringBuilder contentNew = new StringBuilder();
                    Scanner scanner = new Scanner(content);
                    while (scanner.hasNextLine()) {
                        line = scanner.nextLine();
                        line = line.replace("http://www.msjyfund.com.cn/data/kefu/seal_small.png", "http://www.msjyfund.com.cn/data/kefu/seal.png");
                        line = line.replace("http://www.msjyfund.com.cn/data/kefu/", "http://127.0.0.1:8010/ngs/fs/get?file=sms/images/");
                        contentNew.append(line);
                    }

                    contentTemp = contentNew.toString();

                    // 将邮件正文写到本地
                    String htmlFile = mail_HtmlPath + "/" + recGuid + ".html";
                    attachDeleteList.add(htmlFile);
                    boolean bool = writeFile(contentTemp, htmlFile);
                    log.debug("将邮件正文写到本地 是否写入成功：" + bool);

                    //拼接执行路径
                    String zxRoute = mail_htmlFileURL + "/" + recGuid + ".html";
                    //拼接生成PDF文件json格式报文
                    JSONObject jsonObject = new JSONObject();
                    jsonObject.put("ismerge", 1);
                    jsonObject.put("ismark", "");//是否生成电子章，0不生成，1生成
                    JSONObject markinfo = new JSONObject();
                    markinfo.put("markpic", "");//电子章路径
                    markinfo.put("x_axis", 400);//电子章x轴位置
                    markinfo.put("y_axis", 100);//电子章y轴位置
                    markinfo.put("zoom", 25);//像素
                    JSONArray jsonArray = new JSONArray();
                    JSONObject jsonObject1 = new JSONObject();
                    jsonObject1.put("id", "");
                    jsonObject1.put("url", zxRoute);
                    jsonArray.add(jsonObject1);
                    jsonObject.put("markinfo", markinfo);
                    jsonObject.put("value", jsonArray);
                    jsonObject.put("isBatchEmail", 1);//邮件批量标识

                    //调用生成pdf文件接口
                    String PDFUrl = pdfChangeUrl + "apiPDFDeal";
                    String doPostResult = Util.doHttpPost(PDFUrl, jsonObject.toString(), "UTF-8", 600000, 0);
                    JSONObject doResultJson = JSONObject.fromObject(doPostResult.toString());
                    String pdfMergePath = doResultJson.getString("value");

                    // 将当前邮件附件生成的临时文件加入到待删除List
                    if (doResultJson.has("data")) {
                        JSONArray pdfTempFiles = doResultJson.getJSONArray("data");
                        for (int j = 0; j < pdfTempFiles.size(); j++) {
                            pdfTempPath = pdfTempFiles.getJSONObject(j).getString("convPath");
                            if (!KHUtil.isNull(pdfTempPath)) {
                                attachDeleteList.add(pdfTempPath);
                            }

                        }
                    }

                    // 获取PDF文件名和文件路径KHUtil.getRandomString(6)
                    String pdfFileName = pdfMergePath.substring(pdfMergePath.lastIndexOf("/") + 1);
                    String pdfFilePath = pdfMergePath.replace("/" + pdfFileName, "");
                    String newPDFFileName = "民生加银月度对账单" + Util.getNowString("yyyyMMddHHmmss") + "-" + KHUtil.getRandomString(6) + ".pdf";
                    String newPDFFilePath = pdfFilePath + "/" + newPDFFileName;

                    // 将临时文件重命名,并放入到待删除List
                    boolean reNameFlag = Util.renameFile(pdfMergePath, newPDFFileName);
                    attachDeleteList.add(newPDFFilePath);


                    // 添加邮件对应的附件
                    // 1-邮件正文转为PDF后的PDF附件
                    attachmentList.add(newPDFFilePath);
                }
                // 2-邮件自带的附件内容
                if (uploadFlag > 0) {
                    def attachSQL = "select filepath from email_attachment where doctemplate_id='" + templateId + "'";
                    def attachments = eliteBean.chaxun_sql(attachSQL, "dataSource");
                    if (attachments.size() > 0) {
                        for (int j = 0; j < attachments.size(); j++) {
                            log.debug("附件attachments:" + attachments[j].get("filepath"));
                            attachmentList.add(fileStore + "/" + attachments[j].get("filepath"));
                        }
                    }

                }
                log.debug("处理待发送任务[" + i + "]:Rec_Guid" + recGuid + " 拼接template_id:" + templateId + " -attachmentList:" + attachmentList.size());
                //加入发送列表
                receviceMap.put("rec_guid", recGuid);
                receviceMap.put("receviceAddress", receviceAddress);
                receviceMap.put("subject", subject);
                receviceMap.put("content", contents + content);
                receviceMap.put("emlFilePath", emailpath);
                receviceMap.put("attachmentList", attachmentList);

                receviceMap.put("batch_id", batchId);
                receviceMap.put("contenttype", contentType);
                receviceMap.put("relativepath", relativepath);
                receviceMap.put("trialcount", trialCount);
                receviceMap.put("trialcountlimit", trialCountLimit);

                receviceMap.put("sendResult", false);
                receviceMap.put("attachResult", false);

                // 正则表达式检查邮件地址是否是民生邮件,民生邮箱通过exchange方式发送
                Pattern regex = Pattern.compile(mail_AddressCheckReg);
                Matcher matcher = regex.matcher(receviceAddress.toLowerCase());

                boolean isMatched = matcher.matches();
                if (isMatched) {
                    pipe = 1;
                    receviceMap.put("pipe", pipe);
                    // 将这封待发送任务Map插入List
                    exsendList.add(receviceMap);
                    log.debug("Exchange待发送任务Map插入List[" + i + "]-Exchange Num:" + exsendList.size());
                } else {
                    pipe = 2;
                    receviceMap.put("pipe", pipe);
                    // 将这封待发送任务Map插入List
                    umsendList.add(receviceMap);
                    log.debug("UMail待发送任务Map插入List[" + i + "]-UMail Num:" + umsendList.size());

                }
            } catch (Exception e) {

                log.error("EmailSendTask 发送邮件(单条)Exception 数据:" + json.toString() + " 异常详情", e);
            }

        }

        /**
         * 数据处理完成根据通道类型开始调用发送操作
         */
        // 调用发送批量邮件--EX
        if (exsendList.size() > 0) {
            log.debug("Exchange调用发送批量邮件--Num:" + exsendList.size());
            // 调用发送批量邮件
            callSendDeal(eliteBean, exhost, port, exsendAdderss, exusername, expassword, exsendList);
            log.debug("EX-邮件发送成功");
        } else {
            log.debug("Exchange停止调用发送邮件--Num:" + exsendList.size());
        }

        // 调用发送批量邮件--UM
        if (umsendList.size() > 0) {
            log.debug("UMail调用发送批量邮件--Num:" + umsendList.size());
            callSendDeal(eliteBean, umhost, port, umsendAdderss, umusername, umpassword, umsendList);
            log.debug("UM-邮件发送成功");
        } else {
            log.debug("UMail停止调用发送邮件--Num:" + umsendList.size());
        }

        // 全部邮件发送完成后删除邮件中临时文件
        for (int k = 0; k < attachDeleteList.size(); k++) {
            pdfTempPath = attachDeleteList.get(k).toString();
            if (!KHUtil.isNull(pdfTempPath)) {
                KHFileUtil.deleteFiles(pdfTempPath);
            }
        }
        log.debug("批量发送邮件任务执行结束...");

    }

    //批量发送方法
    public static callSendDeal(EliteBean eliteBean, String host, int port, String sendAdderss, String username, String password, List<Map<String, Object>> sendList) {

        // 定义接收批量邮件返回信息
        List resultList = new ArrayList();
        Map<String, Object> resultMap = new HashMap<String, Object>();

        resultList = SendBatchMail.goSendMail(host, port, sendAdderss, username, password, sendList);


        // 处理返回数据
        for (int i = 0; i < resultList.size(); i++) {

            resultMap = (Map<String, Object>) resultList.get(i);

            def batch_id = resultMap.get("batch_id").toString();
            def rec_guid = resultMap.get("rec_guid").toString();
            def trialcount = resultMap.get("trialcount").toString();
            def trialcountlimit = resultMap.get("trialcountlimit").toString();
            def relativepath = resultMap.get("relativepath").toString();
            def pipe = resultMap.get("pipe").toString();
            def sendResult = resultMap.get("sendResult").toString();
            def attachResult = resultMap.get("attachResult").toString();

            if (sendResult.equals("true")) {
                String[] data = new String[3];
                data[0] = "insert into documentout(doctype,documentout_guid,status,trialcount,trialcountlimit,documentpath,comments,subject,documentfrom,documentto,customer_guid,attachflag,batch_id,pipe,sk_invpty,invpty_name,template_id,sendtype,expectedstartdate,createddate,STRINGFIELD1,STRINGFIELD2) select 2,sysguid,1,trialcount+1,trialcountlimit,'" + relativepath + "',subject,subject,'" + sendAdderss + "',email,customer_guid,0,'" + batch_id + "'," + pipe + ",sk_invpty,invpty_name,template_id,2,expectedstartdate,sysdate,'" + sendResult + "', '" + attachResult + "' from email_send_task where rec_guid='" + rec_guid + "'";
                data[1] = "update email_send_batch set quantitysent=quantitysent+1,quantitysucc=quantitysucc+1 where batch_id='" + batch_id + "'";
                data[2] = "delete from email_send_task where rec_guid='" + rec_guid + "'";
                int[] dataresult = eliteBean.updateBatch(data, "dataSource");
            } else {
                trialcount++;
                log.debug("trialcount:" + trialcount);
                if (trialcount < trialcountlimit) {
                    eliteBean.update("update email_send_task set trialcount=trialcount+1 where rec_guid='" + rec_guid + "'", "dataSource");
                } else {
                    String[] data = new String[3];
                    data[0] = "insert into documentout(doctype,documentout_guid,status,trialcount,trialcountlimit,documentpath,comments,subject,documentfrom,documentto,customer_guid,attachflag,batch_id,pipe,sk_invpty,invpty_name,template_id,sendtype,expectedstartdate,createddate,STRINGFIELD1,STRINGFIELD2) select 2,sysguid,5,trialcount+1,trialcountlimit,null,subject,subject,'" + sendAdderss + "',email,customer_guid,0,'" + batch_id + "'," + pipe + ",sk_invpty,invpty_name,template_id,2 ,expectedstartdate,sysdate,'" + sendResult + "', '" + attachResult + "' from email_send_task where rec_guid='" + rec_guid + "'";
                    data[1] = "update email_send_batch set quantitysent=quantitysent+1,quantityfail=quantityfail+1 where batch_id='" + batch_id + "'";
                    data[2] = "delete from email_send_task where rec_guid='" + rec_guid + "'";
                    int[] dataresult = eliteBean.updateBatch(data, "dataSource");
                }
            }

            log.debug("发送结果详情[" + i + "]:Rec_Guid-" + rec_guid + " -sendResult:" + sendResult + " -attachResult:" + attachResult);

        }

    }

    public static boolean writeFile(String fileContent, String FilePath) {

        long tstartTime, tendTime, startTime, endTime;

        tstartTime = System.currentTimeMillis();

        // 将文件内容写入本地服务器
        int i = 0;
        File dirAll = new File(FilePath);
        Writer fw = null;
        PrintWriter pw = null;
        startTime = System.currentTimeMillis();
        try {
            // 文件夹路径是否存在不存在则创建
            File dir = new File(dirAll.getParent());
            if (!dir.exists()) {
                dir.mkdirs();
            }

            // 检查目标文件是否存在，不存在则创建
            if (!dirAll.exists()) {
                boolean flag = dirAll.createNewFile();
            }
            // 向目标文件中写入内容
            fw = new OutputStreamWriter(new FileOutputStream(FilePath), "UTF-8");
            pw = new PrintWriter(fw);
            pw.println(fileContent);
            pw.flush();
            log.debug("-File[" + i + "]写入文件完成...");
        } catch (Exception e) {
            log.error("-File[" + i + "]写入文件失败：", e);
            e.printStackTrace();
        } finally {
            try {
                fw.close();
                pw.close();
            } catch (IOException e) {
                log.warn("文件操作对象释放异常-", e);
            }
            endTime = System.currentTimeMillis();

            log.debug("-File[" + i + "]写入文件结束 Start time:" + startTime + "; End time:" + endTime + "; Run Time:" + (endTime - startTime) + "(ms)");

            i++;

        }

        tendTime = System.currentTimeMillis();
        log.debug("-File写入本地文件结束 End time:" + tendTime + "; Run Time:" + (tendTime - tstartTime) + "(ms)");

        return dirAll.exists();

    }

}